package org.codefinger.json.parser.deserializer;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Date;

import org.codefinger.json.JSONBase;
import org.codefinger.json.parser.JSONArrayDeserializer;
import org.codefinger.json.parser.JSONLexer;
import org.codefinger.json.parser.JSONObjectDeserializer;

public class ArrayDeserializerForCharArray implements JSONArrayDeserializer {

	private static final char[]	DEFAULTCAPACITY_EMPTY_ELEMENTDATA	= new char[0];

	private char[]				elementData							= DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

	private int					size								= 0;

	public ArrayDeserializerForCharArray() {
		super();
	}

	@Override
	public JSONArrayDeserializer createArrayDeserializer() {
		return ArrayDeserializerForNull.INSTANCE;
	}

	@Override
	public JSONObjectDeserializer createObjectDeserializer() {
		return ObjectDeserializerForNull.INSTANCE;
	}

	@Override
	public void addValue(Object value) {
	}

	@Override
	public void addStringValue(JSONLexer jsonLexer) {
		String value = jsonLexer.getJSONString();
		if (value.length() > 0) {
			add(value.charAt(0));
		} else {
			add((char) 0);
		}
	}

	@Override
	public void addIntValue(String value) {
		add((char) Integer.parseInt(value));
	}

	@Override
	public void addFloatValue(String value) {
		add((char) new BigDecimal(value).intValue());
	}

	@Override
	public void addFalseValue() {
	}

	@Override
	public void addTrueValue() {
	}

	@Override
	public void addNullValue() {
	}

	@Override
	public Object getDeserializedValue() {
		return elementData.length == size ? elementData : Arrays.copyOf(elementData, size);
	}

	private void ensureCapacityInternal(int minCapacity) {
		if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
			minCapacity = Math.max(10, minCapacity);
		}
		ensureExplicitCapacity(minCapacity);
	}

	private void ensureExplicitCapacity(int minCapacity) {
		if (minCapacity - elementData.length > 0) {
			grow(minCapacity);
		}
	}

	private void grow(int minCapacity) {
		int oldCapacity = elementData.length;
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		if (newCapacity - minCapacity < 0) {
			newCapacity = minCapacity;
		}
		elementData = Arrays.copyOf(elementData, newCapacity);
	}

	private void add(char value) {
		ensureCapacityInternal(size + 1);
		elementData[size++] = value;
	}

	@Override
	public void addValue(Integer value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(Double value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(Float value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(Long value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(Short value) {
		add((char) value.shortValue());
	}

	@Override
	public void addValue(Byte value) {
		add((char) value.byteValue());
	}

	@Override
	public void addValue(Boolean value) {
	}

	@Override
	public void addValue(Character value) {
		add(value.charValue());
	}

	@Override
	public void addValue(Date value) {
		add((char) value.getTime());
	}

	@Override
	public void addValue(BigDecimal value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(BigInteger value) {
		add((char) value.intValue());
	}

	@Override
	public void addValue(JSONBase value) {
		add((char) value.intValue().intValue());
	}

	@Override
	public void addValue(String value) {
		if (value.length() > 0) {
			add(value.charAt(0));
		} else {
			add((char) 0);
		}
	}

	@Override
	public Object to(int[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(double[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(float[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(long[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(short[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(byte[] value) {
		int length = value.length;
		char[] result = new char[length];
		for (int i = 0; i < length; i++) {
			result[i] = (char) value[i];
		}
		return result;
	}

	@Override
	public Object to(boolean[] value) {
		return DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	}

	@Override
	public Object to(char[] value) {
		return Arrays.copyOf(value, value.length);
	}

}
